from vcbrowser.utils import import_class
from vcbrowser.engine.base import VCBrowserError, EngineError
from urlparse import urlsplit
from pprint import pformat

backends_path = 'vcbrowser.engine.backends'

ENGINE_ALIASES = {
    'svn':          'subversion.svn_pysvn.SubversionEngine',
    'pysvn':        'subversion.svn_pysvn.SubversionEngine',
    'subvertpy':    'subversion.svn_subvertpy.SubvertpyEngine',
    'hg':           'mercurial.hg.MercurialEngine',
}

def engine_by_alias(alias):
    """
    Returns engine class by given alias.
    """
    if not alias in ENGINE_ALIASES:
        raise EngineError("Given alias '%s' is not recognized! "
            "Allowed aliases:\n%s"
            % (alias, pformat(ENGINE_ALIASES.keys())))
    engine_path = '.'.join( (backends_path, ENGINE_ALIASES[alias]) )
    Engine = import_class(engine_path)
    return Engine

def engine_from_url(url):
    """
    Returns engine class by dispatching
    information from url. You may specify
    engine alias and schema by providing
    them at the schema part, splitted with
    - (minus).
    For example:
        url = 'subvertpy-http://code.djangoproject.com/svn/django/trunk/'
    means you are trying to connect to remote
    repository at http://code.djangoproject.com/svn/django/trunk/
    using SubvertpyEngine.
    
    If both, alias and schema splitted with
    - character, are not provided, schema
    is supposed to be an alias and path is
    a local repository path.
    For example:
        url = 'hg:///srv/hg/repositories/my_repo'
    means you are trying to connect to local
    repository at '/srv/hg/repositories/my_repo'
    using MercurialEngine.
    """
    schema, netloc, path, query, fragment = urlsplit(url)
    if not schema or query or fragment:
        raise EngineError("Wrong repository url: %s" % url)
    if '-' in schema:
        alias, schema = schema.split('-')
    else:
        alias = schema
        schema = 'file'
    engine = engine_by_alias(alias)
    repo_path = schema + '://' + path
    return engine(repo_path)

